package com.alibaba.citrus.cr.mn.order.center.facade.adapter.impl;

import com.alibaba.citrus.cr.mn.order.center.facade.adapter.CargoZoneAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.LogisticWarehouseQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.LogisticWarehouseQueryDTO;
import com.alibaba.cloud.retail.store.api.service.CargoZoneQueryService;
import com.alibaba.cloud.retail.store.request.cargozone.QueryCargoZoneByParamDetailRequest;
import com.alibaba.cloud.retail.store.request.cargozone.QueryCargoZoneByParamRequest;
import com.alibaba.cloud.retail.store.request.cargozone.QueryCargoZoneRequest;
import com.alibaba.cloud.retail.store.response.ResultPager;
import com.alibaba.cz.base.model.store.CargoZoneSDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.result.Result;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.model.dto.WarehouseInfo;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author zhangxiaorui
 * @ClassName LogisticWarehouseQueryAdapter
 * @description: TODO
 * @date 2023/05/30 17:56
 * @version: 1.0
 */
@Service
public class CargoZoneAdapterImpl implements CargoZoneAdapter {
    private static final Log log = Log.getLogger(CargoZoneAdapterImpl.class);

    @DubboReference
    private CargoZoneQueryService cargoZoneQueryService;
    @Resource
    private EpochCacheService epochCacheService;

    @Override
    public List<LogisticWarehouseQueryDTO> queryCargoZoneListByParam(List<LogisticWarehouseQueryRequest> requestList) {
        if (CollectionUtils.isEmpty(requestList)) {
            return Lists.newArrayList();
        }

        Set<String> warehouseInfoSet = new HashSet<>();
        List<QueryCargoZoneByParamDetailRequest> reqList = new ArrayList<>();
        for (LogisticWarehouseQueryRequest p : requestList) {
            String key = String.format("%s%s%s", p.getFactoryCode(), p.getStorageLocation(), p.getLogicWarehouseCode());
            if (warehouseInfoSet.contains(key)) {
                continue;
            }

            QueryCargoZoneByParamDetailRequest req = new QueryCargoZoneByParamDetailRequest();
            req.setFactoryCode(p.getFactoryCode());
            req.setStorageLocation(p.getStorageLocation());
            req.setLogicWarehouseCode(p.getLogicWarehouseCode());
            reqList.add(req);
            warehouseInfoSet.add(key);
        }

        QueryCargoZoneByParamRequest cargoZoneByParamRequest = new QueryCargoZoneByParamRequest();
        cargoZoneByParamRequest.setRequestList(reqList);
        Result<List<CargoZoneSDO>> listResult = cargoZoneQueryService.queryCargoZoneListByParam(cargoZoneByParamRequest);
        log.info("逻辑仓库查询 request={}, result={}", JSONObject.toJSONString(cargoZoneByParamRequest), JSONObject.toJSONString(listResult));
        if (Objects.isNull(listResult) || CollectionUtils.isEmpty(listResult.getResult())) {
            return Lists.newArrayList();
        }

        return listResult.getResult()
                .stream()
                .filter(sdo -> sdo.getStatus() == 1) // 1正常 2停用 3关联停用 -1删除
                .map(p -> {
                    LogisticWarehouseQueryDTO queryDTO = new LogisticWarehouseQueryDTO();
                    BeanUtils.copyProperties(p, queryDTO);
                    return queryDTO;
                }).collect(Collectors.toList());
    }

    @Override
    public WarehouseInfo searchCargoZone(String warehouseCode) {
        // 增加缓存，防止并发测试时cpu被打满
        String cacheWarehouseInfo = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(), warehouseCode);
        log.info("查询逻辑仓信息 缓存结果 cacheWarehouseInfo={}", cacheWarehouseInfo);
        if (StringUtils.isNotBlank(cacheWarehouseInfo)) {
            return JSON.parseObject(cacheWarehouseInfo, WarehouseInfo.class);
        }

        QueryCargoZoneRequest request = new QueryCargoZoneRequest();
        request.setCodes(Lists.newArrayList(warehouseCode));
        request.setSize(1);
        request.setStart(0);
        log.info("查询逻辑仓信息, 入参:{}", request);
        Result<ResultPager<List<CargoZoneSDO>>> listResult = cargoZoneQueryService.searchCargoZoneListByDB(request);
        log.info("查询逻辑仓信息, 出参:{}", listResult);
        Map<String, CargoZoneSDO> cargoZoneSDOMap = Optional.ofNullable(listResult)
                .map(Result::getResult).map(ResultPager::getContent).orElse(Lists.newArrayList())
                .stream().collect(Collectors.toMap(CargoZoneSDO::getCode, v -> v));
        CargoZoneSDO cargoZoneSDO = cargoZoneSDOMap.get(warehouseCode);
        if (Objects.isNull(cargoZoneSDO)) {
            return null;
        }

        WarehouseInfo warehouseInfo = WarehouseInfo.builder()
                .id(cargoZoneSDO.getId())
                .code(cargoZoneSDO.getCode()) // 逻辑仓编码
                .name(cargoZoneSDO.getName())
                .sapFactoryCode(cargoZoneSDO.getSapFactoryCode()) // 工厂编码
                .warehouseCode(cargoZoneSDO.getWarehouseCode()) // 库存地点
                .build();

        // 缓存结果，10分钟过期
        epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), warehouseCode, JSON.toJSONString(warehouseInfo), 10L, TimeUnit.MINUTES);

        return warehouseInfo;
    }
}
